/*
 * Copyright (c) 2007 Compl Yue Still, All Rights Reserved.
 */

package oex
{
	import flash.events.*;
	import flash.geom.*;
	import flash.ui.*;
	
	import hbi.as3.utils.*;
	import hbi.domain.*;
	import hbi.domain.as3.*;
	import hbi.wire.as3.*;
	import hbi.wire.as3.host.*;
	
	import mx.core.*;
	import mx.events.*;
	
	import oex.pilot.*;
	import oex.tasks.*;
	import oex.ui.*;
	import oex.ui.shapes.*;
	import flash.display.InteractiveObject;
	import flash.utils.getQualifiedClassName;
	import flash.utils.getDefinitionByName;

	public class ObjectExplorer extends FreeSpace implements DomainController
	{

	    public function get controllerVersion():int
	    {
	        // 1.0
	        return 0x0100;
	    }
	
	    public function isControllerVersionSupported(version:int):Boolean
	    {
	        // enforce exact match here
	        return version == controllerVersion;
	    }
		
		[ArrayElementType("Class")]
		private static const localAgentTypes:Array =
		// keep these classes referenced so not kept out from the swf
		[
			oex.tasks.ShapeApproval,
			oex.tasks.ShapeRelease,
			oex.tasks.Feedback,
		];
	
		private var _gateway:AS3Gateway;
	
		public function ObjectExplorer
			(server:String="localhost", port:int = 11011)
		{
			super();
			
			var sock:SocketOutput = new SocketOutput();
			var hand:ActiveHand = new ActiveHand(this, ObjectWorld, 0x0100,
				sock, established);
			sock.connect(server, port);
		}
		
		private function established(hand:ActiveHand):void
		{
			var sock:SocketOutput = SocketOutput(hand.socket);
			var gateway:AS3Gateway = new AS3Gateway(this, sock);
			var hostEnd:HostEnd = new HostEnd(gateway);
			hostEnd.bindSocket(sock);
			
			this._gateway = gateway;
			
			gateway.sendTaskAgent(RefreshShapes);
		}
		
		override protected function populateContextMenu(cm:ContextMenu):void
		{
			var mi:ContextMenuItem;
			
			mi = new ContextMenuItem("Place Triangle");
			mi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
				function (event:ContextMenuEvent):void
			{
				ObjectExplorer(event.contextMenuOwner).createNewShape
					(new Triangle());
			});
			cm.customItems.push(mi);

			mi = new ContextMenuItem("Place Circle");
			mi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
				function (event:ContextMenuEvent):void
			{
				ObjectExplorer(event.contextMenuOwner).createNewShape
					(new Circle());
			});
			cm.customItems.push(mi);

//			mi = new ContextMenuItem("Test");
//			mi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
//				function (event:ContextMenuEvent):void
//			{
//				new Test(event.contextMenuOwner);
//			});
//			cm.customItems.push(mi);
			
			super.populateContextMenu(cm);
		}
		
		private var _shapes:Object = new Object();
		
		private var _newShapes:Object = new Object();
		private var _nextNewShapeID:int = -1;
		
		public function prepareShape(oid:int, type:String=null):ObjectShape
		{
			if(oid < 0) throw new Error("Negative shape oid!");
			
			var shape:ObjectShape = _shapes[oid];
			if(!shape && type)
			{
				var shapeType:Class = Class(getDefinitionByName(type));
				shape = new shapeType();
				shape.oid = oid;
				shape.redrawShape(0.8);
				super.addShape(shape);
				_shapes[oid] = shape;
			}
			return shape;
		}
		
		public function createNewShape(shape:ObjectShape):void
		{
			shape.oid = _nextNewShapeID--;
			
			shape.redrawShape(0.5);
			super.addShape(shape);
			var p:Point = super.currentCenterPoint();
			shape.move(p.x, p.y);
			
			_newShapes[shape.oid] = shape;			
			_gateway.sendTaskAgent(SubmitShape, function(agent:*):void
			{
				agent.withNewShape(getQualifiedClassName(shape), shape.oid);
				agent.setShapeProperty("color", shape.color);
				agent.setShapeProperty("x", shape.x);
				agent.setShapeProperty("y", shape.y);
				agent.publishShape();
			});
		}
		
		public function newShapeApproved(tempOID:int, assignedOID:int):void
		{
			var shape:ObjectShape = _newShapes[tempOID];
			if(!shape)
			{
				trace("Approved no shape: " + tempOID + "->" + assignedOID);
				return;
			}
			delete _newShapes[tempOID];
			shape.oid = assignedOID;
			_shapes[assignedOID] = shape;
			shape.redrawShape(0.8);
		}
		
		override public function removeShape(shape:ObjectShape):void
		{
			var oid:int = shape.oid;
			if(oid < 0)
			{
				shape.parent.removeChild(shape);
				delete _newShapes[oid];
			}
			else
			{
				shape.redrawShape(0.5);
				_gateway.sendTaskAgent(SubmitShape, function(agent:*):void
				{
					agent.removeShape(shape.oid);
				});
			}
		}
		
		public function shapeRemoved(oid:int):void
		{
			var shape:ObjectShape = _shapes[oid];
			if(!shape)
			{
				trace("Globally removed no shape: " + oid);
				return;
			}
			delete _shapes[oid];
			shape.parent.removeChild(shape);
		}
		
		override public function shapeMoved(shape:ObjectShape):void
		{
			shape.redrawShape(0.5);
			_gateway.sendTaskAgent(SubmitShape, function(agent:*):void
			{
				trace("Moving shape: " + shape.oid);
				agent.withShape(shape.oid);
				agent.setShapeProperty("x", shape.x);
				agent.setShapeProperty("y", shape.y);
				agent.publishShape();
			});
		}
		override public function shapeScaled(shape:ObjectShape):void
		{
			shape.redrawShape(0.5);
			_gateway.sendTaskAgent(SubmitShape, function(agent:*):void
			{
				agent.withShape(shape.oid);
				agent.setShapeProperty("scaleX", shape.scaleX);
				agent.setShapeProperty("scaleY", shape.scaleY);
				agent.publishShape();
			});
		}
		override public function shapeRotated(shape:ObjectShape):void
		{
			shape.redrawShape(0.5);
			_gateway.sendTaskAgent(SubmitShape, function(agent:*):void
			{
				agent.withShape(shape.oid);
				agent.setShapeProperty("rotation", shape.rotation);
				agent.publishShape();
			});
		}
		
		public function get gateway():AS3Gateway
		{
			return _gateway;
		}
		
	}
}
